/**
 * Created by Jellyleo on 2019年12月16日
 * Copyright © 2019 jellyleo.com
 * All rights reserved.
 */
package com.jellyleo.activiti.controller;

import com.alibaba.fastjson2.JSON;
import com.jellyleo.activiti.entity.CommonVariable;
import com.jellyleo.activiti.entity.dto.ProcessDefinitionDTO;
import com.jellyleo.activiti.service.ProcessDefinitionService;
import com.jellyleo.activiti.util.BeanUtil;
import com.woniu.constant.CustomerConstants;
import com.woniu.dto.DirectOrdersDto;
import com.woniu.dto.OrderbillingsUnitDto;
import com.woniu.pojo.AjaxResult;
import com.woniu.pojo.PageParam;
import com.woniu.until.ResponseData;
import com.woniu.until.StringUtils;
import com.woniu.vo.ProcessActiviti;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 功能描述:流程控制器
 *
 * @author Jelly
 * @version 1.0.0
 * @created 2019年11月19日
 */
@RestController
@RequestMapping("/process")
public class ProcessController extends BaseController {
    @Autowired
    private ProcessDefinitionService processDefinitionService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @PostMapping("/list")
    public ResponseData<?> getAllProcessDefinitions(
            @RequestBody PageParam<ProcessDefinitionDTO> pageParam) {
        return processDefinitionService.getProcessDefinitions(pageParam);

    }

    /**
     * 获取流程定义XML
     *
     * @param response
     * @param deploymentId
     * @param resourceName
     */
    @GetMapping(value = "/getDefinitionXML")
    public void getProcessDefineXML(HttpServletResponse response,
                                    @RequestParam("deploymentId") String deploymentId,
                                    @RequestParam("resourceName") String resourceName) throws IOException {

        processDefinitionService.getProcessDefineXML(response, deploymentId, resourceName);
    }

    /**
     * 通过stringBPMN添加流程定义
     *
     * @param stringBPMN
     * @return
     */
    @PostMapping(value = "/addDeploymentByString")
    public AjaxResult addDeploymentByString(@RequestParam("stringBPMN") String stringBPMN) {
        processDefinitionService.addDeploymentByString(stringBPMN);
        return AjaxResult.success();
    }

    /**
     * 上传流程流程定义
     *
     * @param multipartFile
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/upload")
    public AjaxResult upload(@RequestParam("processFile") MultipartFile multipartFile) throws IOException {

        if (!multipartFile.isEmpty()) {
            String fileName = processDefinitionService.upload(multipartFile);
            fileName = fileName.substring("/profile".length());
            return AjaxResult.success("操作成功", fileName);

        }
        return AjaxResult.error("不允许上传空文件！");
    }

    /**
     * 删除流程定义
     *
     * @param deploymentId
     * @return
     */
    @GetMapping(value = "/remove/{deploymentId}")
    public AjaxResult delDefinition(@PathVariable("deploymentId") String deploymentId) {
        return toAjax(processDefinitionService.deleteProcessDefinitionById(deploymentId));
    }

    protected AjaxResult toAjax(int rows) {
        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    /*****************************************************/

//    /**
//     * 功能描述:classpath部署流程
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
//    @RequestMapping(value = "/deploy")
//    @ResponseBody
//    public String deploy(HttpServletRequest request, HttpServletResponse response) {
//
//        String name = request.getParameter("name");
//        String resource = request.getParameter("resource");
//
//        if (StringUtils.isEmpty(resource) || StringUtils.isEmpty(name)) {
//            return "param error";
//        }
//
//        try {
//            // 创建一个部署对象
//            Deployment deploy = repositoryService.createDeployment().name(name)
//                    .addClasspathResource("processes/" + resource).deploy();
//            System.out.println("部署成功:" + deploy.getId());
//            System.out.println("*****************************************************************************");
//        } catch (Exception e) {
//            return "fail";
//        }
//        return "success";
//    }
//
//    /**
//     * 功能描述:zip部署流程
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
//    @RequestMapping(value = "/deploy/zip")
//    @ResponseBody
//    public String deployZip(HttpServletRequest request, HttpServletResponse response) {
//
//        String name = request.getParameter("name");
//        String zip = request.getParameter("zip");
//
//        if (StringUtils.isEmpty(zip) || StringUtils.isEmpty(name)) {
//            return "param error";
//        }
//
//        try {
//            InputStream in = this.getClass().getClassLoader().getResourceAsStream("processes/" + zip);
//            ZipInputStream zipInputStream = new ZipInputStream(in);
//            Deployment deployment = repositoryService// 与流程定义和部署对象相关的Service
//                    .createDeployment()// 创建一个部署对象
//                    .name(name)// 添加部署名称
//                    .addZipInputStream(zipInputStream)// 完成zip文件的部署
//                    .deploy();// 完成部署
//            System.out.println("部署ID：" + deployment.getId());
//            System.out.println("部署名称:" + deployment.getName());
//            System.out.println("*****************************************************************************");
//        } catch (Exception e) {
//            return "fail";
//        }
//        return "success";
//    }
//
//    /**
//     * 功能描述:查询流程定义
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
//    @RequestMapping(value = "/definition/query")
//    @ResponseBody
//    public String processDefinition(HttpServletRequest request, HttpServletResponse response) {
//
//        try {
//            List<ProcessDefinition> list = repositoryService// 与流程定义和部署对象相关的Service
//                    .createProcessDefinitionQuery()// 创建一个流程定义查询
//                    /* 指定查询条件,where条件 */
//                    // .deploymentId(deploymentId)//使用部署对象ID查询
//                    // .processDefinitionId(processDefinitionId)//使用流程定义ID查询
//                    // .processDefinitionKey(processDefinitionKey)//使用流程定义的KEY查询
//                    // .processDefinitionNameLike(processDefinitionNameLike)//使用流程定义的名称模糊查询
//
//                    /* 排序 */
//                    .orderByProcessDefinitionVersion().asc()// 按照版本的升序排列
//                    // .orderByProcessDefinitionName().desc()//按照流程定义的名称降序排列
//
//                    .list();// 返回一个集合列表，封装流程定义
//            // .singleResult();//返回唯一结果集
//            // .count();//返回结果集数量
//            // .listPage(firstResult, maxResults)//分页查询
//
//            if (list != null && list.size() > 0) {
//                for (ProcessDefinition processDefinition : list) {
//                    System.out.println("流程定义ID:" + processDefinition.getId());// 流程定义的key+版本+随机生成数
//                    System.out.println("流程定义名称:" + processDefinition.getName());// 对应HelloWorld.bpmn文件中的name属性值
//                    System.out.println("流程定义的key:" + processDefinition.getKey());// 对应HelloWorld.bpmn文件中的id属性值
//                    System.out.println("流程定义的版本:" + processDefinition.getVersion());// 当流程定义的key值相同的情况下，版本升级，默认从1开始
//                    System.out.println("资源名称bpmn文件:" + processDefinition.getResourceName());
//                    System.out.println("资源名称png文件:" + processDefinition.getDiagramResourceName());
//                    System.out.println("部署对象ID:" + processDefinition.getDeploymentId());
//                    System.out.println("*****************************************************************************");
//                }
//            }
//        } catch (Exception e) {
//            return "fail";
//        }
//        return "success";
//    }

//    /**
//     * 功能描述:删除流程定义
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
//    @RequestMapping(value = "/deployment/delete")
//    @ResponseBody
//    public String deleteDeployment(HttpServletRequest request, HttpServletResponse response) {
//
//        String deploymentId = request.getParameter("deployId");
//
//        if (StringUtils.isEmpty(deploymentId)) {
//            return "param error";
//        }
//
//        try {
////			// 不带级联的删除：只能删除没有启动的流程，如果流程启动，则抛出异常
////			repositoryService.deleteDeployment(deploymentId);
//            // 能级联的删除：能删除启动的流程，会删除和当前规则相关的所有信息，正在执行的信息，也包括历史信息
//            repositoryService.deleteDeployment(deploymentId, true);
//            System.out.println("删除成功:" + deploymentId);
//            System.out.println("*****************************************************************************");
//        } catch (Exception e) {
//            return "fail";
//        }
//        return "success";
//    }
//
//    /**
//     * 功能描述:启动流程
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
    @RequestMapping(value = "/start")
    @ResponseBody
    public String start(@RequestBody ProcessActiviti<OrderbillingsUnitDto> processActiviti) {

        String processDefinitionKey = processActiviti.getProcessId();
        String businessKey = processActiviti.getBusinessKey();
        String variable = null;
        if (StringUtils.isEmpty(processDefinitionKey)) {
            return "param error";
        }


        try {
            Map<String, Object> variables = new HashMap<>();
            if (!StringUtils.isEmpty(variable)) {
                CommonVariable variablesEntity = JSON.parseObject(variable, CommonVariable.class);
                variables = BeanUtil.beanToMap(variablesEntity);
            }

//            ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
//			// Businesskey:业务标识，通常为业务表的主键，业务标识和流程实例一一对应。业务标识来源于业务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据
            ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey,
                    variables);


            OrderbillingsUnitDto customer = processActiviti.getData();
            redisTemplate.opsForHash().put("customer", instance.getId(), JSON.toJSONString(customer));
            runtimeService.setVariable(instance.getProcessInstanceId(),"businessKey",businessKey);
            System.out.println("流程实例ID:" + instance.getId());
            System.out.println("流程定义ID:" + instance.getProcessDefinitionId());
            System.out.println("*****************************************************************************");
        } catch (Exception e) {
            e.printStackTrace();
            return "fail";
        }
        return "success";
    }
    @RequestMapping(value = "/startOrder")
    @ResponseBody
    public String startOrder(@RequestBody ProcessActiviti<DirectOrdersDto> processActiviti) {

        String processDefinitionKey = processActiviti.getProcessId();
        String businessKey = processActiviti.getBusinessKey();
        String variable = null;
        if (StringUtils.isEmpty(processDefinitionKey)) {
            return "param error";
        }


        try {
            Map<String, Object> variables = new HashMap<>();
            if (!StringUtils.isEmpty(variable)) {
                CommonVariable variablesEntity = JSON.parseObject(variable, CommonVariable.class);
                variables = BeanUtil.beanToMap(variablesEntity);
            }

//            ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, variables);
//			// Businesskey:业务标识，通常为业务表的主键，业务标识和流程实例一一对应。业务标识来源于业务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据
            ProcessInstance instance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey,
                    variables);


            DirectOrdersDto ordersDto = processActiviti.getData();
            redisTemplate.opsForHash().put("order", instance.getId(), JSON.toJSONString(ordersDto));
            runtimeService.setVariable(instance.getProcessInstanceId(), "businessKey", businessKey);
            System.out.println("流程实例ID:" + instance.getId());
            System.out.println("流程定义ID:" + instance.getProcessDefinitionId());
            System.out.println("*****************************************************************************");
        } catch (Exception e) {
            e.printStackTrace();
            return "fail";
        }
        return "success";
    }
//
//    /**
//     * 功能描述:删除流程
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
//    @RequestMapping(value = "/delete")
//    @ResponseBody
//    public String deleteProcess(HttpServletRequest request, HttpServletResponse response) {
//
//        String processId = request.getParameter("processId");
//
//        if (StringUtils.isEmpty(processId)) {
//            return "param error";
//        }
//
//        try {
//            runtimeService.deleteProcessInstance(processId, "流程已完毕");
//            System.out.println("终止流程");
//            System.out.println("*****************************************************************************");
//        } catch (Exception e) {
//            return "fail";
//        }
//        return "success";
//    }
//
//    /**
//     * 功能描述:流程实例挂起
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
//    @RequestMapping(value = "/instance/suspend")
//    @ResponseBody
//    public String suspendProcessInstance(HttpServletRequest request, HttpServletResponse response) {
//
//        String processInstanceId = request.getParameter("processInstanceId");
//
//        if (StringUtils.isEmpty(processInstanceId)) {
//            return "param error";
//        }
//
//        try {
//            // 根据一个流程实例的id挂起该流程实例
//            runtimeService.suspendProcessInstanceById(processInstanceId);
//            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
//                    .processInstanceId(processInstanceId).singleResult();
//            System.out.println("流程实例ID:" + processInstance.getId());
//            System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
//            System.out.println("流程实例状态:" + processInstance.isSuspended());
//            System.out.println("*****************************************************************************");
//        } catch (Exception e) {
//            return "fail";
//        }
//        return "success";
//    }
//
//    /**
//     * 功能描述:流程定义挂起
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
//    @RequestMapping(value = "/definition/suspend")
//    @ResponseBody
//    public String suspendProcessDefinition(HttpServletRequest request, HttpServletResponse response) {
//
//        String processDefinitionId = request.getParameter("processDefinitionId");
//
//        if (StringUtils.isEmpty(processDefinitionId)) {
//            return "param error";
//        }
//
//        try {
//            // 根据一个流程定义的id挂起该流程实例
//            repositoryService.suspendProcessDefinitionByKey(processDefinitionId);
//            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
//                    .processDefinitionKey(processDefinitionId).singleResult();
//            System.out.println("流程定义ID:" + processDefinition.getId());
//            System.out.println("流程定义状态:" + processDefinition.isSuspended());
//            System.out.println("*****************************************************************************");
//        } catch (Exception e) {
//            return "fail";
//        }
//        return "success";
//    }
//
//    /**
//     * 功能描述:流程实例激活
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
//    @RequestMapping(value = "/instance/activate")
//    @ResponseBody
//    public String activateProcessInstance(HttpServletRequest request, HttpServletResponse response) {
//
//        String processInstanceId = request.getParameter("processInstanceId");
//
//        if (StringUtils.isEmpty(processInstanceId)) {
//            return "param error";
//        }
//
//        try {
//            // 根据一个流程实例id激活该流程
//            runtimeService.activateProcessInstanceById(processInstanceId);
//            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
//                    .processInstanceId(processInstanceId).singleResult();
//            System.out.println("流程实例ID:" + processInstance.getId());
//            System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
//            System.out.println("流程实例状态:" + processInstance.isSuspended());
//            System.out.println("*****************************************************************************");
//        } catch (Exception e) {
//            return "fail";
//        }
//        return "success";
//    }
//
//    /**
//     * 功能描述:流程定义激活
//     *
//     * @param request
//     * @param response
//     * @see [相关类/方法](可选)
//     * @since [产品/模块版本](可选)
//     */
//    @RequestMapping(value = "/definition/activate")
//    @ResponseBody
//    public String activateProcessDefinition(HttpServletRequest request, HttpServletResponse response) {
//
//        String processDefinitionId = request.getParameter("processDefinitionId");
//
//        if (StringUtils.isEmpty(processDefinitionId)) {
//            return "param error";
//        }
//
//        try {
//            // 根据一个流程定义的id挂起该流程实例
//            repositoryService.activateProcessDefinitionById(processDefinitionId);
//            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
//                    .processDefinitionKey(processDefinitionId).singleResult();
//            System.out.println("流程定义ID:" + processDefinition.getId());
//            System.out.println("流程定义状态:" + processDefinition.isSuspended());
//            System.out.println("*****************************************************************************");
//        } catch (Exception e) {
//            return "fail";
//        }
//        return "success";
//    }
}
